using System;
using System.IO;
using System.Threading.Tasks;
using EasyNetQ;
using MalwareMultiScan.Api.Data.Configuration;
using MalwareMultiScan.Api.Data.Models;
using MalwareMultiScan.Api.Services.Interfaces;
using MalwareMultiScan.Backends.Messages;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace MalwareMultiScan.Api.Services.Implementations
{
    /// <inheritdoc />
    public class ScanBackendService : IScanBackendService
    {
        private readonly IBus _bus;
        private readonly ILogger<ScanBackendService> _logger;

        /// <summary>
        /// Initialise scan backend service.
        /// </summary>
        /// <param name="configuration">Configuration.</param>
        /// <param name="bus">EasyNetQ bus.</param>
        /// <param name="logger">Logger.</param>
        /// <exception cref="FileNotFoundException">Missing backends.yaml configuration.</exception>
        public ScanBackendService(IConfiguration configuration, IBus bus, ILogger<ScanBackendService> logger)
        {
            _bus = bus;
            _logger = logger;

            var configurationPath = configuration.GetValue<string>("BackendsConfiguration");

            if (!File.Exists(configurationPath))
                throw new FileNotFoundException("Missing BackendsConfiguration YAML file", configurationPath);

            var configurationContent = File.ReadAllText(configurationPath);

            var deserializer = new DeserializerBuilder()
                .WithNamingConvention(CamelCaseNamingConvention.Instance)
                .Build();

            List = deserializer.Deserialize<ScanBackend[]>(configurationContent);
        }

        /// <inheritdoc />
        public ScanBackend[] List { get; }

        /// <inheritdoc />
        public async Task QueueUrlScan(ScanResult result, ScanBackend backend, string fileUrl)
        {
            _logger.LogInformation(
                $"Queueing scan for {result.Id} on {backend.Id} at {fileUrl}");

            await _bus.SendAsync(backend.Id, new ScanRequestMessage
            {
                Id = result.Id,
                Uri = new Uri(fileUrl)
            });
        }
    }
}